package main

import "fmt"

func gReduce[T1 any, T2 any](arr []T1, init T2, f func(T2, T1) T2) T2 {
	result := init
	for _, elem := range arr {
		result = f(result, elem)
	}
	return result
}

func gReduce1[T any](arr []T, init T, f func(T, T) T) T {
	result := init
	for _, elem := range arr {
		result = f(result, elem)
	}
	return result
}

type Sumable interface {
	int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | float32 | float64
}

func gSum[T any, U Sumable](arr []T, f func(T) U) U {
	var sum U
	for _, elem := range arr {
		sum += f(elem)
	}

	return sum
}

func main() {
	nums := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	sum := gReduce1(nums, 0, func(result, elem int) int {
		return result + elem
	})
	fmt.Println(sum)
	fmt.Println(gSum(nums, func(ele int) int {
		return ele
	}))
}
